/*
 * $Id:
 *
 * Copyright (C) 2011 Refiner Inc.
 * All right reserved
 *
 *============================================================
 * +rVPN Stack : AppIF (Application Interface)
 *============================================================
 * abstract: AppIFでのメッセージ通信用
 * author  : MURATA
 * history :
 *
 */

#ifndef _RVS_MSG_H_
#define _RVS_MSG_H_

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <poll.h>
#include <netdb.h>
#include <sys/select.h>
#include "rvs_helpif.h"

#pragma pack(4)

#define	RVSA_MAGIC		0x41535652
#define	USERNAMELEN		15

#define rvs_malloc(s)       malloc(s)
#define rvs_realloc(m,s)    realloc(m,s)
#define rvs_free(m)         free(m)

/*------------------------------------*
 * AppIF メッセージヘッダ             *
 *------------------------------------*/
typedef struct rvs_api_hdr {
    uint32_t    magic;        /* Magic Code 'RVSA' */
    uint16_t    msgcode;      /* メッセージコード */
    uint16_t    seqno;        /* シーケンシャル番号 */
    int32_t     status;       /* 処理結果 */
    int32_t     length;       /* ペイロード長 */
} rvs_api_hdr_t;

/*------------------------------------*
 * AppIF パラメータ(TLV)              *
 *------------------------------------*/
typedef struct rvs_api_tlv {
    uint16_t    Type;        /* パラメータタイプ */
    uint16_t    Length;      /* パラメータ長 */
    int32_t     Value[0];
} rvs_api_tlv_t;

/*------------------------------------*
 * AppIF タイプ別パラメータ           *
 *------------------------------------*/

/*
 * AppIF パラメータ(Integer)
 */
typedef struct rvs_api_int {
    uint16_t    Type;        /* パラメータタイプ */
    uint16_t    Length;      /* パラメータ長 */
    int32_t     Integer;     /* パラメータ値 */
} rvs_api_int_t;

/*
 * for Node, Service, Value
 */
typedef struct rvs_api_str {
    uint16_t    Type;        /* パラメータタイプ */
    uint16_t    Length;      /* パラメータ長 */
    char        String[0];
} rvs_api_str_t;

/*
 * Data with User Buffer
 */
typedef struct rvs_api_ubuf {
    uint16_t    Type;        /* パラメータタイプ */
    uint16_t    Length;      /* パラメータ長 */
    const char* Buffer;
} rvs_api_ubuf_t;

/*
 * for Addr(IPv4)
 */
typedef struct rvs_api_av4 {
    uint16_t      Type;        /* パラメータタイプ */
    uint16_t      Length;      /* パラメータ長 */
    uint16_t      Reserved;    /* Reserved */
    uint16_t      PortNo;      /* Port No.(ネットワークバイトオーダー) */
    uint32_t      IPAddress;   /* IP Address (IPv4)ネットワークバイトオーダー */
} rvs_api_av4_t;

/*
 * for Addr(IPv6)
 */
typedef struct rvs_api_av6 {
    uint16_t      Type;        /* パラメータタイプ */
    uint16_t      Length;      /* パラメータ長 */
    uint16_t      Reserved;    /* Reservedネットワークバイトオーダー */
    uint16_t      PortNo;      /* Port No.ネットワークバイトオーダー */
    uint32_t      FlowInfo;    /* Flow Info.ネットワークバイトオーダー */
    struct in6_addr Address;   /* IP Address (IPv6)ネットワークバイトオーダー */
    uint32_t      ScopeID;     /* Scope ID */
} rvs_api_av6_t;

/*
 * for AddrInfo
 */
typedef struct rvs_api_ai {
    uint16_t      Type;        /* パラメータタイプ */
    uint16_t      Length;      /* パラメータ長 */
    uint32_t      Flags;       /* Flags */
    uint32_t      Family;      /* Address Family */
    uint32_t      SockType;    /* Socket Type */
    uint32_t      Protocol;    /* Protocol */
    union {
        rvs_api_av4_t AddrV4;      /*   IPv4 */
        rvs_api_av6_t AddrV6;      /*   IPv6 */
    }             Address;
} rvs_api_ai_t;

/*
 * for AddrList
 */
typedef struct rvs_api_ail {
    uint16_t      Type;        /* パラメータタイプ */
    uint16_t      Length;      /* パラメータ長 */
    rvs_api_ai_t  AddrInfo[1]; /* AddrInfo */
} rvs_api_ail_t;

/*
 * for SockEvent
 */
typedef struct rvs_api_sev {
    uint16_t    Type;        /* パラメータタイプ */
    uint16_t    Length;      /* パラメータ長 */
    int32_t     rSocket;     /* rSocket */
    uint16_t    ReqEvents;   /* Req-Events */
    uint16_t    Events;      /* Events */
} rvs_api_sev_t;

/*
 * for SockEventList
 */
typedef struct rvs_api_sel {
    uint16_t      Type;        /* パラメータタイプ */
    uint16_t      Length;      /* パラメータ長 */
    rvs_api_sev_t SockEvent[1];/* SockEvent */
} rvs_api_sel_t;

/*
 * for StatusInfo
 */
typedef struct rvs_api_status {
    uint16_t      Type;        /* パラメータタイプ */
    uint16_t      Length;      /* パラメータ長 */
    uint16_t      VPNStat;     /* センターVPN接続状態 */
    uint16_t      P2PCount;    /* P2P接続数 */
    rvs_api_str_t Remote[0];   /* リモートユーザID */
} rvs_api_status_t;

/*
 * for ErrorInfo
 */
typedef struct rvs_api_error {
    uint16_t      Type;        /* パラメータタイプ */
    uint16_t      Length;      /* パラメータ長 */
    uint16_t      RequestType; /* エラーを起こした要求種別 */
    uint16_t      ReasonType;  /* エラーコードタイプ */
    union {
        uint16_t  RCode2[2];   /* エラーコード(2ワードタイプ) */
        uint8_t   RCode3[3];   /* エラーコード(3バイトタイプ) */
    }  ErrCode;
    rvs_api_str_t Remote[0];   /* (P2P-VPNエラーの場合)相手ユーザID */
} rvs_api_error_t;

/*------------------------------------*
 * AppIF メッセージ構造体(受信用)     *
 *------------------------------------*/
typedef struct rvs_api_msg {
    uint16_t         aloc;     /* ヒープから確保したかどうか */
    uint16_t         baloc;    /* バッファをヒープから確保したかどうか */
    rvs_api_hdr_t*   header;   /* メッセージヘッダ */
    rvs_api_int_t*   rsock;    /* rSocket */
    rvs_api_int_t*   rerr;     /* ErrorNo */
    rvs_api_ubuf_t*  data;     /* Data */
    rvs_api_int_t*   flags;    /* Flags */
    rvs_api_int_t*   timeout;  /* Timeout */
    rvs_api_int_t*   level;    /* Level */
    rvs_api_int_t*   option;   /* Option */
    rvs_api_str_t*   value;    /* Value */
    rvs_api_int_t*   domain;   /* Domain */
    rvs_api_int_t*   type;     /* Type */
    rvs_api_int_t*   proto;    /* Protocol */
    rvs_api_int_t*   backlog;  /* BackLog */
    rvs_api_int_t*   how;      /* How */
    rvs_api_str_t*   node;     /* Node */
    rvs_api_str_t*   serv;     /* Service */
    rvs_api_sev_t*   sevent;   /* SockEvent */
    rvs_api_av4_t*   addrv4;   /* Addr(IPv4) */
    rvs_api_av4_t*   daddrv4;  /* Dest Addr(IPv4) */
    rvs_api_av6_t*   addrv6;   /* Addr(IPv6) */
    rvs_api_av6_t*   daddrv6;  /* Dest Addr(IPv6) */
    rvs_api_ai_t*    ainfo;    /* AddrInfo */
    rvs_api_ail_t*   alist;    /* AddrList */
    rvs_api_sel_t*   selist;   /* SockEventList */
    rvs_api_str_t*   userid;   /* UserID */
    rvs_api_int_t*   vifno;     /* Interface No.*/
    rvs_api_status_t* statinfo;/* Status Info. */
    rvs_api_error_t* errinfo;  /* Error Info. */
} rvs_api_msg_t;

/*------------------------------------*
 * AppIF メッセージ構造体(送信用)     *
 *------------------------------------*/
#define RVS_SBUF_BLOCK    256
typedef struct rvs_api_send {
    int32_t          size;    /* バッファ部分の現在のサイズ */
    rvs_api_tlv_t*   next;
    rvs_api_hdr_t    header;  /* メッセージヘッダ */
    char             buffer[0];
} rvs_api_send_t;

/*------------------------------------*
 * AppIF メッセージコード             *
 *------------------------------------*/
#define RAPI_M_RESPONSE        0x8000     /* レスポンスフラグ */
#define RAPI_M_RESP(x)         (RAPI_M_RESPONSE|(x))
                                        /* レスポンスコード */
#define RAPI_M_IS_REQ(x)       (((x)&RAPI_M_RESPONSE) == 0)
                                        /* リクエストかどうかの判定 */
#define RAPI_M_IS_RESP(x)      (((x)&RAPI_M_RESPONSE) != 0)
                                        /* レスポンスかどうかの判定 */
#define	RAPI_M_CODE(x)         ((x)|(~RAPI_M_RESPONSE))

#define RAPI_M_SOCKET          0x0001
#define RAPI_M_SOCKET_RES      RAPI_M_RESP(RAPI_M_SOCKET)
#define RAPI_M_CLOSE           0x0002
#define RAPI_M_CLOSE_RES       RAPI_M_RESP(RAPI_M_CLOSE)
#define RAPI_M_BIND            0x0003
#define RAPI_M_BIND_RES        RAPI_M_RESP(RAPI_M_BIND)
#define RAPI_M_CONNECT         0x0004
#define RAPI_M_CONNECT_RES     RAPI_M_RESP(RAPI_M_CONNECT)
#define RAPI_M_LISTEN          0x0005
#define RAPI_M_LISTEN_RES      RAPI_M_RESP(RAPI_M_LISTEN)
#define RAPI_M_ACCEPT          0x0006
#define RAPI_M_ACCEPT_RES      RAPI_M_RESP(RAPI_M_ACCEPT)
#define RAPI_M_SENDTO          0x0011
#define RAPI_M_SENDTO_RES      RAPI_M_RESP(RAPI_M_SENDTO)
#define RAPI_M_RECVFROM        0x0012
#define RAPI_M_RECVFROM_RES    RAPI_M_RESP(RAPI_M_RECVFROM)
#define RAPI_M_SEND            0x0013
#define RAPI_M_SEND_RES        RAPI_M_RESP(RAPI_M_SEND)
#define RAPI_M_RECV            0x0014
#define RAPI_M_RECV_RES        RAPI_M_RESP(RAPI_M_RECV)
#define RAPI_M_SETSOCKOPT      0x0021
#define RAPI_M_SETSOCKOPT_RES  RAPI_M_RESP(RAPI_M_SETSOCKOPT)
#define RAPI_M_GETSOCKOPT      0x0022
#define RAPI_M_GETSOCKOPT_RES  RAPI_M_RESP(RAPI_M_GETSOCKOPT)
#define RAPI_M_GETADDRINFO     0x0023
#define RAPI_M_GETADDRINFO_RES RAPI_M_RESP(RAPI_M_GETADDRINFO)
#define RAPI_M_GETSOCKNAME     0x0024
#define RAPI_M_GETSOCKNAME_RES RAPI_M_RESP(RAPI_M_GETSOCKNAME)
#define RAPI_M_IOCTL           0x0025
#define RAPI_M_IOCTL_RES       RAPI_M_RESP(RAPI_M_IOCTL)
#define RAPI_M_FCNTL           0x0026
#define RAPI_M_FCNTL_RES       RAPI_M_RESP(RAPI_M_FCNTL)
#define RAPI_M_SHUTDOWN        0x0027
#define RAPI_M_SHUTDOWN_RES    RAPI_M_RESP(RAPI_M_SHUTDOWN)
#define RAPI_M_SELECT          0x0031
#define RAPI_M_SELECT_RES      RAPI_M_RESP(RAPI_M_SELECT)
#define RAPI_M_GETLOCALIF      0x0041
#define RAPI_M_GETLOCALIF_RES  RAPI_M_RESP(RAPI_M_GETLOCALIF)
#define RAPI_M_GETVIFROUTE     0x0042
#define RAPI_M_GETVIFROUTE_RES RAPI_M_RESP(RAPI_M_GETVIFROUTE)
#define RAPI_M_STATUSCHECK     0x0043
#define RAPI_M_STATUSCHECK_RES RAPI_M_RESP(RAPI_M_STATUSCHECK)

/*------------------------------------*
 * AppIF パラメータタイプ             *
 *------------------------------------*/
#define RAPI_P_SOCKET          0x0001    /* rSocket */
#define RAPI_P_ERRNO           0x0002    /* ErrorNo */
#define RAPI_P_DATA            0x0003    /* Data */
#define RAPI_P_FLAGS           0x0004    /* Flags */
#define RAPI_P_TIMEOUT         0x0005    /* Timeout */
#define RAPI_P_LEVEL           0x0006    /* Level */
#define RAPI_P_OPTION          0x0007    /* Option */
#define RAPI_P_REQUEST         0x0007    /* Request */
#define RAPI_P_COMMAND         0x0007    /* Command */
#define RAPI_P_VALUE           0x0008    /* Value */
#define RAPI_P_DOMAIN          0x0009    /* Domain */
#define RAPI_P_TYPE            0x000A    /* Type */
#define RAPI_P_PROTOCOL        0x000B    /* Protocol */
#define RAPI_P_BACKLOG         0x000C    /* BackLog */
#define RAPI_P_NODE            0x000D    /* Node */
#define RAPI_P_SERVICE         0x000E    /* Service */
#define RAPI_P_HOW             0x000F    /* How(shutdown) */
#define RAPI_P_SOCKEVENT       0x0010    /* SockEvent */
#define RAPI_P_USERID          0x0020    /* UserID */
#define RAPI_P_VIFNO           0x0021    /* VIF No. */
#define RAPI_P_ADDRV4          0x0101    /* Addr(IPv4) */
#define RAPI_P_DADDRV4         0x8101    /* Dest Addr(IPv4) */
#define RAPI_P_ADDRV6          0x0102    /* Addr(IPv6) */
#define RAPI_P_DADDRV6         0x8102    /* Dest Addr(IPv6) */
#define RAPI_P_ADDRINFO        0x0103    /* AddrList */
#define RAPI_P_ADDRLIST        0x0201    /* AddrList */
#define RAPI_P_SEVENTLIST      0x0202    /* SockEventList */
#define RAPI_P_STATINFO        0x0301    /* StatusInfo */
#define RAPI_P_ERRINFO         0x0302    /* ErrorInfo */

/*------------------------------------*
 * AppIF 関数定義                     *
 *------------------------------------*/
#ifdef __cplusplus
extern "C"{
#endif

/* rvs_free_msg - 受信メッセージ構造体の解放 */
void rvs_free_msg(rvs_api_msg_t* msg);

typedef char* (*ubuf_func_t)(int* length, void* param);

/* rvs_recv_msg - メッセージ受信 */
rvs_api_msg_t* rvs_recv_msg (int sock, rvs_api_msg_t* msg,
           int msgcode, int seqno,
           char* rbuf, int rbuflen, ubuf_func_t getbuf, void* param);

/* rvs_send_msg - メッセージ送信 */
int rvs_send_msg (int sock, rvs_api_send_t* msg);

/* rvs_make_msg - メッセージ作成 */
rvs_api_send_t* rvs_make_msg (int msgcode, int seqno, int status);

/* rvs_add_int - 整数型パラメータの追加 */
int rvs_add_int (rvs_api_send_t* msg, int type, int val);

/* rvs_add_rsock - rSocketパラメータの追加 */
static inline int rvs_add_rsock(rvs_api_send_t* msg, int rsock)
{
    return rvs_add_int(msg, RAPI_P_SOCKET, rsock);
}

/* rvs_add_errno - ErrNoパラメータの追加 */
static inline int rvs_add_errno(rvs_api_send_t* msg, int err)
{
    return rvs_add_int(msg, RAPI_P_ERRNO, err);
}

/* rvs_add_data - Dataパラメータの追加 */
int rvs_add_data (rvs_api_send_t* msg, const char* buf, int buflen);

/* rvs_add_flags - Flagsパラメータの追加 */
static inline int rvs_add_flags(rvs_api_send_t* msg, int flags)
{
    return rvs_add_int(msg, RAPI_P_FLAGS, flags);
}

/* rvs_add_tout - Timeoutパラメータの追加 */
static inline int rvs_add_tout(rvs_api_send_t* msg, int tout)
{
    return rvs_add_int(msg, RAPI_P_TIMEOUT, tout);
}

/* rvs_add_level - Levelパラメータの追加 */
static inline int rvs_add_level(rvs_api_send_t* msg, int level)
{
    return rvs_add_int(msg, RAPI_P_LEVEL, level);
}

/* rvs_add_opt - Optionパラメータの追加 */
static inline int rvs_add_opt(rvs_api_send_t* msg, int opt)
{
    return rvs_add_int(msg, RAPI_P_OPTION, opt);
}

/* rvs_add_request - Requestパラメータの追加 */
static inline int rvs_add_request(rvs_api_send_t* msg, int request)
{
    return rvs_add_int(msg, RAPI_P_REQUEST, request);
}

/* rvs_add_cmd - Commandパラメータの追加 */
static inline int rvs_add_cmd(rvs_api_send_t* msg, int cmd)
{
    return rvs_add_int(msg, RAPI_P_COMMAND, cmd);
}

/* rvs_add_void - 可変長パラメータの追加 */
int rvs_add_void (rvs_api_send_t* msg, int type, const char* buf, int buflen);

/* rvs_add_valus - Valueパラメータの追加 */
static inline int rvs_add_value(rvs_api_send_t* msg, const void* value, int vallen)
{
    return rvs_add_void(msg, RAPI_P_VALUE, value, vallen);
}

/* rvs_add_domain - Domainパラメータの追加 */
static inline int rvs_add_domain(rvs_api_send_t* msg, int domain)
{
    return rvs_add_int(msg, RAPI_P_DOMAIN, domain);
}

/* rvs_add_type - Typeパラメータの追加 */
static inline int rvs_add_type(rvs_api_send_t* msg, int type)
{
    return rvs_add_int(msg, RAPI_P_TYPE, type);
}

/* rvs_add_proto - Protocolパラメータの追加 */
static inline int rvs_add_proto(rvs_api_send_t* msg, int proto)
{
    return rvs_add_int(msg, RAPI_P_PROTOCOL, proto);
}

/* rvs_add_backlog - BackLogパラメータの追加 */
static inline int rvs_add_backlog(rvs_api_send_t* msg, int backlog)
{
    return rvs_add_int(msg, RAPI_P_BACKLOG, backlog);
}

/* rvs_add_how - How(shutdown)パラメータの追加 */
static inline int rvs_add_how(rvs_api_send_t* msg, int how)
{
    return rvs_add_int(msg, RAPI_P_HOW, how);
}

/* rvs_add_vifno - vifnoパラメータの追加 */
static inline int rvs_add_vifno(rvs_api_send_t* msg, int vifno)
{
    return rvs_add_int(msg, RAPI_P_VIFNO, vifno);
}

/* rvs_add_node - Nodeパラメータの追加 */
static inline int rvs_add_node(rvs_api_send_t* msg, char* node)
{
    return rvs_add_void(msg, RAPI_P_NODE, node, strlen(node));
}

/* rvs_add_serv - Serviceパラメータの追加 */
static inline int rvs_add_serv(rvs_api_send_t* msg, char* serv)
{
    return rvs_add_void(msg, RAPI_P_SERVICE, serv, strlen(serv));
}

/* rvs_add_sevent - SockEventパラメータの追加 */
int rvs_add_sevent (rvs_api_send_t* msg, struct pollfd *pfd);

/* rvs_add_selist - SockEventListパラメータの追加 */
int rvs_add_selist (rvs_api_send_t* msg, struct pollfd *pfds, int nfds);

/* rvs_add_fdsets - SockEventListパラメータの追加 */
int rvs_add_fdsets (rvs_api_send_t* msg, int nfds,
            fd_set *readfds, fd_set *writefds, fd_set *exceptfds);

/* rvs_add_addrv4 - AddrV4パラメータの追加 */
int rvs_add_addrv4 (rvs_api_send_t* msg, const struct sockaddr_in *addr);

/* rvs_add_addrv6 - AddrV6パラメータの追加 */
int rvs_add_addrv6 (rvs_api_send_t* msg, const struct sockaddr_in6 *addr);

/* rvs_add_addr, rvs_add_daddr - Addrressパラメータの追加 */
int rvs_add_addr (rvs_api_send_t* msg, const struct sockaddr *addr);
int rvs_add_daddr (rvs_api_send_t* msg, const struct sockaddr *addr);

/* rvs_add_ainfo - AddrInfoパラメータの追加 */
int rvs_add_ainfo (rvs_api_send_t* msg, struct addrinfo *ai);

/* rvs_add_alist - AddrListパラメータの追加 */
int rvs_add_alist (rvs_api_send_t* msg, struct addrinfo *al);

/* rvs_get_addr, rvs_get_daddr - Addressパラメータの取得 */
int rvs_get_addr (rvs_api_msg_t* msg, struct sockaddr *addr, int addrlen);
int rvs_get_daddr (rvs_api_msg_t* msg, struct sockaddr *addr, int addrlen);

/* rvs_get_fdsets - イベント発生FD情報の取得 */
int rvs_get_fdsets (rvs_api_msg_t* msg,
            fd_set *readfds, fd_set *writefds, fd_set *exceptfds);

/* rvs_add_statinfo - ステータス情報パラメータの追加 */
int rvs_add_statinfo (rvs_api_send_t* msg, const rvs_status_t* statusp);

/* rvs_add_errinfo - エラー情報パラメータの追加 */
int rvs_add_errinfo (rvs_api_send_t* msg, const rvs_error_t* errorp);

#ifdef __cplusplus
}
#endif

#endif /* _RVS_MSG_H_ */
